package de.tum.team26.eistpoll.client;

import java.util.LinkedList;

import de.tum.team26.eistpoll.client.UI.*;
import de.tum.team26.eistpoll.shared.PollData;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * Entry point class with Entry Point Procedure
 * @author patrickhiesel
 */
public class EIST_POLL implements EntryPoint {

	// init GWT Calls:
	private PollServiceAsync pollServiceSvc = GWT.create(PollService.class);
	// Main UI Element
	private UIElement poll = new Loading(this);

	/**
	 * Entry point Method
	 */
	public void onModuleLoad() {
		// attatch Main Panel to site
		RootPanel.get("poll").add(this.poll.getContainer());
		// decide which Panel to show
		triggerFirstUI();
	}
	
	/**
	 * Method to decide which Panel to show
	 */
	public void triggerFirstUI() {
		// Initialize the service proxy.
		if (pollServiceSvc == null) {
			pollServiceSvc = GWT.create(PollService.class);
		}
		// Set up the callback object.
		AsyncCallback<PollData> callback = new AsyncCallback<PollData>() {
			public void onFailure(Throwable caught) {
				// TODO: Do something with errors.
			}
			@Override
			public void onSuccess(PollData result) {
				if (result == null) {
					triggerInactive();
				}
				else{
					// decide if user has already voted
					if (result.alreadyVoted){
						triggerAlreadyVoted(result);
					}
					else{
						triggerPoll(result);
					}
				}
			}
		};
		// Call
		pollServiceSvc.getActivePoll(callback);
	}
	
	/**
	 * Show the AlreadyVoted UI
	 * @param poll DataObject
	 */
	public void triggerAlreadyVoted(PollData poll){
		if (this.poll != null) RootPanel.get("poll").remove(this.poll.getContainer());
		this.poll = new AlreadyVoted(this);
		RootPanel.get("poll").add(this.poll.getContainer());
	}
	
	/**
	 *  Show the All Polls Inactive UI
	 */
	public void triggerInactive(){
		if (this.poll != null) RootPanel.get("poll").remove(this.poll.getContainer());
		this.poll = new Inactive(this);
		RootPanel.get("poll").add(this.poll.getContainer());
	}
		
	/**
	 * Show the Poll UI
	 * @param poll DataObject => Identifies the Poll
	 */
	public void triggerPoll(PollData poll){
		if (this.poll != null) RootPanel.get("poll").remove(this.poll.getContainer());
		this.poll = new Poll(poll.getId(), poll.title, this);
		RootPanel.get("poll").add(this.poll.getContainer());
	}
	
	/**
	 * Show the Statistics Panel (student)
	 */
	public void triggerStatistic() {
		if (this.poll != null) RootPanel.get("poll").remove(this.poll.getContainer());
		poll = new Results(false,this);
		RootPanel.get("poll").add(poll.getContainer());
	}
	
	/**
	 * Show the Login Panel
	 */
	public void triggerLogin(){
		if (this.poll != null) RootPanel.get("poll").remove(this.poll.getContainer());
		poll = new Login(this);
		RootPanel.get("poll").add(poll.getContainer());
	}
	
	/**
	 * Show the Admin Panel
	 */
	public void triggerAdminCP(){
		if (this.poll != null) RootPanel.get("poll").remove(this.poll.getContainer());
		poll = new AdminCP(this);
		RootPanel.get("poll").add(poll.getContainer());
	}
	
	
	/**
	 * get Results from server
	 * @param isLecturer Identifies weather the User is a Lecturer or a Student
	 */
	public void getResults(boolean isLecturer){
		// Initialize the service proxy.
		if (pollServiceSvc == null) {
			pollServiceSvc = GWT.create(PollService.class);
		}
		// Set up the callback object.
		AsyncCallback<LinkedList<PollData>> callback = new AsyncCallback<LinkedList<PollData>>() {
			public void onFailure(Throwable caught) {
				poll.displayErrorMessage("RPC Error");
			}
			@Override
			public void onSuccess(LinkedList<PollData> result) {
				// Decide where to update the results
				if (poll instanceof AdminCP){
					((AdminCP) poll).updateResults(result);
				}
				else if (poll instanceof Results){
					((Results) poll).updateResults(result);
				}
				else{
					poll.displayErrorMessage("Error");
				}
				establishPushConnection();
			}
		};
		// Call
		pollServiceSvc.getResults(isLecturer, callback);
	}
	
	/**
	 * Try to log the user in
	 * @param login UI Panel
	 * @param user Username
	 * @param pass Password
	 */
	public void tryLogin(Login login, String user, String pass) {
		// Initialize the service proxy.
		if (pollServiceSvc == null) {
			pollServiceSvc = GWT.create(PollService.class);
		}
		// Set up the callback object.
		AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>() {
			public void onFailure(Throwable caught) {
				poll.displayErrorMessage("RPC Error");
			}
			@Override
			public void onSuccess(Boolean result) {
				// Dice wether to show the AdminCP or the Incorrect inputs Panel
				if (result){
					triggerAdminCP();
				}
				else{
					poll.displayErrorMessage("Wrong username / password!");
				}		
			}
		};
		// Call
		pollServiceSvc.checkUser(user, pass, callback);
	}
	
	/**
	 * Submitt Poll to the Server
	 * @param id PollID
	 * @param option Option of Poll
	 * @param like Like String
	 * @param dislike Dislike String
	 */
	public void submitPoll(int id, int option, String like, String dislike){
		// Initialize the service proxy.
		if (pollServiceSvc == null) {
			pollServiceSvc = GWT.create(PollService.class);
		}
		// Set up the callback object.
		AsyncCallback<Void> callback = new AsyncCallback<Void>() {
			public void onFailure(Throwable caught) {
				poll.displayErrorMessage("RPC Error");
			}
			@Override
			public void onSuccess(Void result) {
				// remove Poll and Trigger Statistic
				RootPanel.get("poll").remove(poll.getContainer());
				triggerStatistic();
			}
		};
		// Call
		pollServiceSvc.pushPollData(id, option, like, dislike, callback);
	}
	
	/**
	 * Reset Poll
	 * @param id Id of Poll to Reset
	 */
	public void resetStatistic(int id) {
		// Initialize the service proxy.
		if (pollServiceSvc == null) {
			pollServiceSvc = GWT.create(PollService.class);
		}

		// Set up the callback object.
		AsyncCallback<Void> callback = new AsyncCallback<Void>() {
			public void onFailure(Throwable caught) {
				poll.displayErrorMessage("RPC Error");
			}
			@Override
			public void onSuccess(Void result) {
				// renew view
				getResults(true);
			}
		};
		// Call
		pollServiceSvc.resetStatistic(id, callback);
	}

	/**
	 * Delete Poll
	 * @param id Id of Poll to delete
	 */
	public void deletePoll(int id) {
		// Initialize the service proxy.
		if (pollServiceSvc == null) {
			pollServiceSvc = GWT.create(PollService.class);
		}
		// Set up the callback object.
		AsyncCallback<Void> callback = new AsyncCallback<Void>() {
			public void onFailure(Throwable caught) {
				poll.displayErrorMessage("RPC Error");
			}
			@Override
			public void onSuccess(Void result) {
				// renew view
				getResults(true);
			}
		};
		// Call
		pollServiceSvc.deletePoll(id, callback);
	}
	
	/**
	 * Switch which Poll should be active
	 * @param id ID of Poll to switch state
	 */
	public void switchPollActive(int id) {
		// Initialize the service proxy.
		if (pollServiceSvc == null) {
			pollServiceSvc = GWT.create(PollService.class);
		}
		// Set up the callback object.
		AsyncCallback<Void> callback = new AsyncCallback<Void>() {
			public void onFailure(Throwable caught) {
				poll.displayErrorMessage("RPC Error");
			}
			@Override
			public void onSuccess(Void result) {
				// renew view
				getResults(true);
			}
		};
		// Call
		pollServiceSvc.switchPollActive(id, callback);
	}
	
	/**
	 * Add a Poll
	 * @param title Title of Poll to add
	 */
	public void addPoll(String title) {
		// Initialize the service proxy.
		if (pollServiceSvc == null) {
			pollServiceSvc = GWT.create(PollService.class);
		}
		// Set up the callback object.
		AsyncCallback<Void> callback = new AsyncCallback<Void>() {
			public void onFailure(Throwable caught) {
				poll.displayErrorMessage("RPC Error");
			}
			@Override
			public void onSuccess(Void result) {
				// renew view
				getResults(true);
			}
		};
		// Call
		pollServiceSvc.addPoll(title, callback);
	}
	
	/**
	 * Establish Connection for Push Service
	 */
	public void establishPushConnection() {
		// Initialize the service proxy.
		if (pollServiceSvc == null) {
			pollServiceSvc = GWT.create(PollService.class);
		}
		// Set up the callback object.
		AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>() {
			public void onFailure(Throwable caught) {
				poll.displayErrorMessage("RPC Error");
			}
			@Override
			public void onSuccess(Boolean result) {
				// Decide if Results must be updated
				if (result){
					if (poll instanceof AdminCP) getResults(true);
					if (poll instanceof Results) getResults(false);
				}		
				else{
					establishPushConnection();
				}
			}
		};
		// Call
		pollServiceSvc.pushService(callback);
	}
}
